﻿using System;
using System.Collections.Generic;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using NDBGen.Descriptors.Columns.Tokens;
using NDBGen.Descriptors.Tables.Tokens;
using NDBGen.Plugins.DataAccess;

namespace NDBGen.Tests
{
    [TestClass]
    public class TableTests : UnitTestBase<DataAccessGeneratorPluginData>
    {
        protected override DataAccessGeneratorPluginData GetPluginData(ParsedInput parsedInput)
        {
            return parsedInput.CreateDataAccessPluginData();
        }

        [TestMethod]
        public void Can_Parse_EnumIdentifier()
        {
            var expected = new Table
            {
                Schema = "dbo",
                Name = "permissions"
            }.AddDescriptors(new EnumTokenDescriptor());
            expected.Columns = new List<Column>
            {
                new Column(expected, "id", DataType.Int).AddDescriptors(new PrimaryKeyTokenDescriptor(), new EnumValueTokenDescriptor()),
                new Column(expected, "name", DataType.VarChar, 20).AddDescriptors(new EnumIdentifierTokenDescriptor())
            };
            var text =
@"permissions|#
    id|int|*#
    name|varchar,20|#";

            var actual = new Table(text, null).Parse();
            Assert.AreEqual(expected, actual);
        }

        [TestMethod]
        public void Can_Parse_FlagsIdentifier()
        {
            var expected = new Table
            {
                Schema = "dbo",
                Name = "permissions"
            }.AddDescriptors(
                new EnumTokenDescriptor(),
                new FlagsEnumTokenDescriptor());
            expected.Columns = new List<Column>
            {
                new Column(expected, "id", DataType.Int).AddDescriptors(new PrimaryKeyTokenDescriptor(), new EnumValueTokenDescriptor()),
                new Column(expected, "name", DataType.VarChar, 20).AddDescriptors(new EnumIdentifierTokenDescriptor())
            };
            var text =
@"permissions|#&
    id|int|*#
    name|varchar,20|#";

            var actual = new Table(text, null).Parse();
            Assert.AreEqual(expected, actual);
        }

        [TestMethod]
        public void Can_Parse_Single_Table()
        {
            var expected = new Table
            {
                Schema = "dbo",
                Name = "admins"
            };
            expected.Columns = new List<Column>
                {
                    new Column(null, "id", DataType.Int).AddDescriptors(new PrimaryKeyTokenDescriptor(), new AutoGeneratedTokenDescriptor(), new IdentityDeclarationTokenDescriptor() ),
                    new Column(null, "username", DataType.VarChar, 50 ),
                    new Column(null, "password_hash", DataType.Binary, 20 ),
                    new Column(null, "password_salt", DataType.Binary, 20 ),
                    new Column(null, "full_name", DataType.NVarChar, 100 ),
                    new Column(null, "email", DataType.NVarChar, 100 ),
                    new Column(null, "inserted_on_utc", DataType.DateTime).AddDescriptor<DefaultValueTokenDescriptor>("getutcdate()"),
                    new Column(null, "is_active", DataType.Bit).AddDescriptor<DefaultValueTokenDescriptor>("0")
                };
            var text =
@"admins
    id|int|@*
    username|varchar,50
    password_hash|binary,20
    password_salt|binary,20
    full_name|nvarchar,100
    email|nvarchar,100
    inserted_on_utc|datetime|=getutcdate()
    is_active|bit|=0";

            var actual = new Table(text, null).Parse();

            Assert.AreEqual(expected, actual);
        }

        [TestMethod]
        public void Can_Parse_Lots_of_Tables()
        {
            var expectedTables = new List<Table>
            {
                new Table
                {
                    Schema = "auth",
                    Name = "table1",
                    Columns = new List<Column>
                    {
                        new Column(null, "id", DataType.Int).AddDescriptors(new PrimaryKeyTokenDescriptor(), new AutoGeneratedTokenDescriptor(), new IdentityDeclarationTokenDescriptor()),
                        new Column(null, "name", DataType.VarChar, 10)
                    }
                },
                new Table
                {
                    Schema = "auth",
                    Name = "table2",
                    Columns = new List<Column>
                    {
                        new Column(null, "id", DataType.Int).AddDescriptors(new PrimaryKeyTokenDescriptor(), new AutoGeneratedTokenDescriptor(), new IdentityDeclarationTokenDescriptor()),
                        new Column(null, "name", DataType.VarChar, 20)
                    }
                },
                new Table
                {
                    Schema = "dbo",
                    Name = "table3",
                    Columns = new List<Column>
                    {
                        new Column(null, "id", DataType.Int).AddDescriptors(new PrimaryKeyTokenDescriptor(), new AutoGeneratedTokenDescriptor(), new IdentityDeclarationTokenDescriptor()),
                        new Column(null, "name", DataType.VarChar, 30)
                    }
                },
                new Table
                {
                    Schema = "dbo",
                    Name = "table4",
                    Columns = new List<Column>
                    {
                        new Column(null, "id", DataType.Int).AddDescriptors(new PrimaryKeyTokenDescriptor(), new AutoGeneratedTokenDescriptor(), new IdentityDeclarationTokenDescriptor()),
                        new Column(null, "name", DataType.VarChar, 40)
                    }
                },
                new Table
                {
                    Schema = "makeme",
                    Name = "table5",
                    Columns = new List<Column>
                    {
                        new Column(null, "id", DataType.Int).AddDescriptors(new PrimaryKeyTokenDescriptor(), new AutoGeneratedTokenDescriptor(), new IdentityDeclarationTokenDescriptor()),
                        new Column(null, "name", DataType.VarChar, 50)
                    }
                },
                new Table
                {
                    Schema = "makeme",
                    Name = "table6",
                    Columns = new List<Column>
                    {
                        new Column(null, "id", DataType.Int).AddDescriptors(new PrimaryKeyTokenDescriptor(), new AutoGeneratedTokenDescriptor(), new IdentityDeclarationTokenDescriptor()),
                        new Column(null, "name", DataType.VarChar, 60)
                    }
                }
            };
            var text =
@"auth
    table1
        id|int|@*
        name|varchar,10
    table2
        id|int|@*
        name|varchar,20
dbo
    table3
        id|int|@*
        name|varchar,30
    table4
        id|int|@*
        name|varchar,40
makeme
    table5
        id|int|@*
        name|varchar,50
    table6
        id|int|@*
        name|varchar,60";

            var actualTables = Parser.ParseTables(text);
            Assert.AreEqual(expectedTables.Count, actualTables.Count);
            for (Int32 i = 0; i < expectedTables.Count; i++)
            {
                var expected = expectedTables[i];
                var actual = actualTables[i];
                Assert.AreEqual(expected, actual);
            }
        }
    }
}